from pprint import pprint
from app_sql.database import engine
from sqlalchemy.engine import reflection
from app_sql.models import Menu
from app_sql.models import Role
from app_sql.models import GeetestNode
import autopep8
from jinja2 import Template
from pprint import pprint

# autopep8 是一个自动格式化 Python 代码的工具，但它不提供直接去除空白行的功能。你可以使用其他方法，比如正则表达式替换，来实现这个需求。

# 下面是一个使用 Python 的简单脚本，它读取 Python 文件，并使用正则表达式去除所有的空白行：

import re


# fields_list = [
#     {
#         "name": "id",
#         "type": "Integer",
#         "primary_key": True,
#         "field_desc": "主键",
#     },
#     {
#         "name": "role_name",
#         "type": "String",
#         "primary_key": False,
#         "field_desc": "角色名",
#     }
# ]
base_path = "./app_sql"

table_name = GeetestNode.__tablename__
model_name = GeetestNode.__name__


def write_code_into_file(content="", dest_path=None):
    def remove_empty_lines(content):
        # 使用正则表达式去除空行
        content_without_empty_lines = re.sub(r"^\s*\n", "", content, flags=re.MULTILINE)
        return content_without_empty_lines

    content = remove_empty_lines(content)
    # content = autopep8.fix_code(content)
    with open(dest_path, "w", encoding="utf8") as writer:
        writer.write(content)


def create_meta_data(models_object):
    table_name = models_object.__tablename__
    model_name = models_object.__name__
    insp = reflection.Inspector.from_engine(engine)

    # schema: 数据库名称
    # table_names = insp.get_table_names()
    # 表名，库名
    table_columns = insp.get_columns(table_name=table_name)
    pprint(table_columns)

    fields_list = []
    type_choices = {
        "integer": "Integer",
        "varchar": "String",
        "boolean": "Boolean",
    }
    for item in table_columns:
        print(item)
        print(item.get("primary_key"))
        item_primary_key = False
        item_name = ""
        item_comment = ""
        item_type = ""
        item_field_desc = ""
        if item.get("primary_key"):
            item_field_desc = "主键"
            item_primary_key = True
        if item.get("name"):
            item_name = item.get("name")
            item_comment = getattr(getattr(models_object, item_name), "comment")
            if not item_comment:
                item_comment = "未知"
            print(item_comment)

        if item.get("type"):
            type_str = item.get("type").__str__().lower()
            print(type_str)
            item_type = type_choices.get(type_str)
        item_dict = {
            "name": item_name,
            "type": item_type,
            "primary_key": item_primary_key,
            "field_desc": item_field_desc,
            "comment": item_comment,
        }
        fields_list.append(item_dict)
    ######################################
    context = {
        "table_name": table_name,
        "model_name": model_name,
        "fields_list": fields_list,
    }
    ######################################
    return context


context = create_meta_data(GeetestNode)

pprint(context)

template_entity = """
export interface {{model_name }} {
    {% for item in fields_list %}
    {% if item.type == 'String' %}
  {{item.name}}: string;
{% elif item.type == 'Integer' %}
  {{item.name}}: number;
{% elif item.type == 'Boolean' %}
  {{item.name}}: boolean;

  {% else %}
  {{item.name}}: 1;
    {% endif %}
    {%  endfor%}
}
"""
template = Template(template_entity)
pprint(context)
rendered = template.render(context)
write_code_into_file(content=rendered, dest_path="./{name}.tsx".format(name=model_name))
print(rendered)

template_service = """
import apiClient from '../apiClient';


export enum {{model_name}}Api {
  {{model_name}} = '/{{model_name|lower}}',
}


// ##################################
export interface {{model_name }} {
    {% for item in fields_list %}
    {% if item.type == 'String' %}
  {{item.name}}: string;
{% elif item.type == 'Integer' %}
  {{item.name}}: number;
{% elif item.type == 'Boolean' %}
  {{item.name}}: boolean;

  {% else %}
  {{item.name}}: 1;
    {% endif %}
    {%  endfor%}
}


export interface {{model_name }}PostReq {
    {% for item in fields_list %}
    {% if item.type == 'String' %}
  {{item.name}}: string;
{% elif item.type == 'Integer' %}
  {{item.name}}: number;
{% elif item.type == 'Boolean' %}
  {{item.name}}: boolean;

  {% else %}
  {{item.name}}: 1;
    {% endif %}
    {%  endfor%}
}

// ##################################

const get{{model_name}}List =()=>apiClient.get< {{model_name}}[]>({ url: {{model_name}}Api.{{model_name}} });
const get{{model_name}} =()=>apiClient.get< {{model_name}}[]>({ url: {{model_name}}Api.{{model_name}} });
const post{{model_name}} =(data:{{model_name }}PostReq)=>apiClient.get< {{model_name}}[]>({ url: {{model_name}}Api.{{model_name}},data });
const put{{model_name}} =(data:{{model_name }}PostReq)=>apiClient.get< {{model_name}}[]>({ url: {{model_name}}Api.{{model_name}},data });
const delete{{model_name}} =()=>apiClient.get< {{model_name}}[]>({ url: {{model_name}}Api.{{model_name}} });

export default {
  get{{model_name}}List,
  get{{model_name}},
  post{{model_name}},
  put{{model_name}},
  delete{{model_name}}
};

"""
template = Template(template_service)
rendered = template.render(context)
write_code_into_file(
    content=rendered, dest_path="./{name}_service.ts".format(name=model_name)
)
print(rendered)


template_page = """
import { useQuery } from '@tanstack/react-query';
import {
  Button,
  Card,
  Col,
  Form,
  Input,
  InputNumber,
  Modal,
  Popconfirm,
  Radio,
  Row,
  Select,
  Space,
} from 'antd';
import Table, { ColumnsType } from 'antd/es/table';
import { TableRowSelection } from 'antd/es/table/interface';
import { useEffect, useState } from 'react';
import orgService from '@/api/services/orgService';
import { IconButton, Iconify } from '@/components/icon';
import ProTag from '@/theme/antd/components/tag';
import { Organization } from '#/entity';
type SearchFormFieldType = Pick<Organization, 'name' | 'status'>;
export default function OrganizationPage() {
  const [searchForm] = Form.useForm();
  const [organizationModalPros, setOrganizationModalProps] = useState<OrganizationModalProps>({
    formValue: {
      id: '',
      name: '',
      status: 'enable',
    },
    title: 'New',
    show: false,
    onOk: () => {
      setOrganizationModalProps((prev) => ({ ...prev, show: false }));
    },
    onCancel: () => {
      setOrganizationModalProps((prev) => ({ ...prev, show: false }));
    },
  });
  const columns: ColumnsType<Organization> = [
    { title: 'Name', dataIndex: 'name', width: 300 },
    { title: 'Order', dataIndex: 'order', align: 'center', width: 60 },
    {
      title: 'Status',
      dataIndex: 'status',
      align: 'center',
      width: 120,
      render: (status) => (
        <ProTag color={status === 'enable' ? 'success' : 'error'}>{status}</ProTag>
      ),
    },
    { title: 'Desc', dataIndex: 'desc', align: 'center', width: 300 },
    {
      title: 'Action',
      key: 'operation',
      align: 'center',
      width: 100,
      render: (_, record) => (
        <div className="flex w-full justify-center text-gray">
          <IconButton onClick={() => onEdit(record)}>
            <Iconify icon="solar:pen-bold-duotone" size={18} />
          </IconButton>
          <Popconfirm title="Delete the Organization" okText="Yes" cancelText="No" placement="left">
            <IconButton>
              <Iconify icon="mingcute:delete-2-fill" size={18} className="text-error" />
            </IconButton>
          </Popconfirm>
        </div>
      ),
    },
  ];
  // rowSelection objects indicates the need for row selection
  const rowSelection: TableRowSelection<Organization> = {
    onChange: (selectedRowKeys, selectedRows) => {
      console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
    },
    onSelect: (record, selected, selectedRows) => {
      console.log(record, selected, selectedRows);
    },
    onSelectAll: (selected, selectedRows, changeRows) => {
      console.log(selected, selectedRows, changeRows);
    },
  };
  const { data } = useQuery({
    queryKey: ['orgs'],
    queryFn: orgService.getOrgList,
  });
  const onSearchFormReset = () => {
    searchForm.resetFields();
  };
  const onCreate = () => {
    setOrganizationModalProps((prev) => ({
      ...prev,
      show: true,
      title: 'Create New',
      formValue: {
        ...prev.formValue,
        id: '',
        name: '',
        order: 1,
        desc: '',
        status: 'enable',
      },
    }));
  };
  const onEdit = (formValue: Organization) => {
    setOrganizationModalProps((prev) => ({
      ...prev,
      show: true,
      title: 'Edit',
      formValue,
    }));
  };
  return (
    <Space direction="vertical" size="large" className="w-full">
      <Card>
        <Form form={searchForm}>
          <Row gutter={[16, 16]}>
            <Col span={24} lg={6}>
              <Form.Item<SearchFormFieldType> label="Name" name="name" className="!mb-0">
                <Input />
              </Form.Item>
            </Col>
            <Col span={24} lg={6}>
              <Form.Item<SearchFormFieldType> label="Status" name="status" className="!mb-0">
                <Select>
                  <Select.Option value="enable">
                    <ProTag color="success">Enable</ProTag>
                  </Select.Option>
                  <Select.Option value="disable">
                    <ProTag color="error">Disable</ProTag>
                  </Select.Option>
                </Select>
              </Form.Item>
            </Col>
            <Col span={24} lg={12}>
              <div className="flex justify-end">
                <Button onClick={onSearchFormReset}>Reset</Button>
                <Button type="primary" className="ml-4">
                  Search
                </Button>
              </div>
            </Col>
          </Row>
        </Form>
      </Card>
      <Card
        title="Organization List"
        extra={
          <Button type="primary" onClick={onCreate}>
            New
          </Button>
        }
      >
        <Table
          rowKey="id"
          size="small"
          scroll={{ x: 'max-content' }}
          pagination={false}
          columns={columns}
          dataSource={data}
          rowSelection={{ ...rowSelection }}
        />
      </Card>
      <OrganizationModal {...organizationModalPros} />
    </Space>
  );
}
type OrganizationModalProps = {
  formValue: Organization;
  title: string;
  show: boolean;
  onOk: VoidFunction;
  onCancel: VoidFunction;
};
function OrganizationModal({ title, show, formValue, onOk, onCancel }: OrganizationModalProps) {
  const [form] = Form.useForm();
  useEffect(() => {
    form.setFieldsValue({ ...formValue });
  }, [formValue, form]);
  return (
    <Modal title={title} open={show} onOk={onOk} onCancel={onCancel}>
      <Form
        initialValues={formValue}
        form={form}
        labelCol={{ span: 4 }}
        wrapperCol={{ span: 18 }}
        layout="horizontal"
      >
        <Form.Item<Organization> label="Name" name="name" required>
          <Input />
        </Form.Item>
        <Form.Item<Organization> label="Order" name="order" required>
          <InputNumber style={{ width: '100%'  }} />
        </Form.Item>
        <Form.Item<Organization> label="Status" name="status" required>
          <Radio.Group optionType="button" buttonStyle="solid">
            <Radio value="enable"> Enable </Radio>
            <Radio value="disable"> Disable </Radio>
          </Radio.Group>
        </Form.Item>
        <Form.Item<Organization> label="Desc" name="desc">
          <Input.TextArea />
        </Form.Item>
      </Form>
    </Modal>
  );
}  
"""
hold_string = {
    "{{": "##start",
    "}}": "##end",
}
hold_string_reverse = {}
for item_key, item_value in hold_string.items():
    template_page = template_page.replace(item_key, item_value)
    hold_string_reverse[item_value] = item_key


template = Template(template_page)
rendered = template.render(context)

for item_key, item_value in hold_string_reverse.items():
    rendered = rendered.replace(item_key, item_value)

write_code_into_file(
    content=rendered, dest_path="./{name}_page.ts".format(name=model_name)
)
print(rendered)
